package org.budo.graph.druid.dubbo.filter;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;
import java.util.Map;

import org.budo.support.java.net.util.JavaNetUtil;
import org.budo.support.lang.util.ArrayUtil;
import org.budo.support.lang.util.ProcessUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.slf4j.Slf4j;
import org.budo.support.spring.context.aware.BudoApplicationContextAware;
import org.budo.time.Time;
import org.slf4j.Logger;
import org.springframework.context.ApplicationContext;

import com.alibaba.dubbo.config.ApplicationConfig;

/**
 * @author li
 */
public abstract class AbstractBudoGraphDruidDubboFilter {
    private static final Logger log = Slf4j.getLogger();

    public String buildUserAgent() {
        StringBuffer stringBuffer = new StringBuffer();
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();

        stringBuffer.append("name=").append(runtimeMXBean.getName());

        long startTime = runtimeMXBean.getStartTime();
        String startTimeString = Time.when(startTime).toString("yyyyMMdd-HHmmss-SSS");
        stringBuffer.append(", startTime=").append(startTimeString);

        Map<String, String> systemProperties = runtimeMXBean.getSystemProperties();
        stringBuffer.append(", os.name=").append(systemProperties.get("os.name"));
        stringBuffer.append(", os.version=").append(systemProperties.get("os.version"));
        stringBuffer.append(", os.arch=").append(systemProperties.get("os.arch"));
        stringBuffer.append(", user.name=").append(systemProperties.get("user.name"));
        stringBuffer.append(", user.dir=").append(systemProperties.get("user.dir"));
        stringBuffer.append(", java.io.tmpdir=").append(systemProperties.get("java.io.tmpdir"));
        stringBuffer.append(", file.encoding=").append(systemProperties.get("file.encoding"));
        stringBuffer.append(", sun.jnu.encoding=").append(systemProperties.get("sun.jnu.encoding"));
        stringBuffer.append(", java.class.version=").append(systemProperties.get("java.class.version"));
        stringBuffer.append(", java.runtime.version=").append(systemProperties.get("java.runtime.version"));

        return stringBuffer.toString();
    }

    public String buildSessionId() {
        BudoApplicationContextAware applicationContextAware = BudoApplicationContextAware.getInstance();
        StringBuffer stringBuffer = new StringBuffer();

        if (null != applicationContextAware) { // BudoApplicationContextAware 已经准备好
            String appName = this.getAppName();
            stringBuffer.append(appName);
            stringBuffer.append("_");
        }

        String processName = ProcessUtil.getCurrentProcessName();
        stringBuffer.append(processName); // 17120@li-pc-2
        stringBuffer.append("_");

        String startTime = Time.when(ProcessUtil.getStartTime()).toString("yyyyMMdd_HHmm");
        stringBuffer.append(startTime);
        return stringBuffer.toString();
    }

    private String getAppName() {
        BudoApplicationContextAware budoApplicationContextAware = BudoApplicationContextAware.getInstanceNoNull();
        ApplicationContext applicationContext = budoApplicationContextAware.getApplicationContext();

        String[] beanNames = applicationContext.getBeanNamesForType(ApplicationConfig.class);
        if (ArrayUtil.isEmpty(beanNames)) {
            return "NoAppConf";
        }

        if (beanNames.length > 1) {
            log.error("#125 TooManyApplicationConfig, " + StringUtil.join(beanNames));
            return "TooManyAppConf";
        }

        ApplicationConfig applicationConfig = (ApplicationConfig) applicationContext.getBean(beanNames[0]);
        String appName = applicationConfig.getName();
        if (null == appName || appName.trim().isEmpty()) {
            log.error("#132 appName is empty, applicationConfig=" + applicationConfig);
            return "AppConfNameEmpty";
        }

        return appName;
    }

    public String buildRemoteAddress() {
        List<String> ipAddresses = JavaNetUtil.getIpAddresses();
        return StringUtil.join(ipAddresses);
    }
}
